/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-09-14 10:12:12
 * @LastEditTime: 2021-09-15 18:23:05
 * @Description:  This files is for sdmmc hardware interface definition
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 */
#ifndef BSP_DRIVERS_F_SDMMC_HW_H
#define BSP_DRIVERS_F_SDMMC_HW_H

#ifdef __cplusplus
extern "C"
{
#endif

#include "kernel.h"
#include "parameters.h"
#include "ft_io.h"
#include "ft_types.h"

/* Register Offset */
#define FSDMMC_CONTROLL_SETTING_REG_OFFSET 0x00    /* Controller configuration register */
#define FSDMMC_ARGUMENT_REG_OFFSET 0x04            /* Parameter register */
#define FSDMMC_CMD_SETTING_REG_OFFSET 0x08         /* Command register */
#define FSDMMC_CLOCK_DIV_REG_OFFSET 0x0C           /* Clock division register */
#define FSDMMC_SOFTWARE_RESET_REG_OFFSET 0x10      /* Reset control register */
#define FSDMMC_POWER_CONTROLL_REG_OFFSET 0x14      /* Power control register */
#define FSDMMC_TIMEOUT_CMD_REG_OFFSET 0x18         /* Cmd Timeout setting register */
#define FSDMMC_TIMEOUT_DATA_REG_OFFSET 0x1C        /* Data timeout setting register */
#define FSDMMC_NORMAL_INT_EN_REG_OFFSET 0x20       /* Interrupt Enable Register */
#define FSDMMC_ERROR_INT_EN_REG_OFFSET 0x24        /* error Interrupt Enable Register */
#define FSDMMC_BD_ISR_EN_REG_OFFSET 0x28           /* Data Transfer Interrupt Enable Register */
#define FSDMMC_CAPABILIES_REG_OFFSET 0x2c          /* capabilies register */
#define FSDMMC_SD_DRV_REG_OFFSET 0x30              /* SD card driver phase register */
#define FSDMMC_SD_SAMP_REG_OFFSET 0x34             /* SD card sampling phase register */
#define FSDMMC_SD_SEN_REG_OFFSET 0x38              /* Card detection controller */
#define FSDMMC_HDS_AXI_REG_CONF1_REG_OFFSET 0x3c   /* AXI boundary configuration register 1 */
#define FSDMMC_DAT_IN_M_RX_BD_REG_OFFSET 0x40      /*  SD BD RX address register */
#define FSDMMC_DAT_IN_M_TX_BD_REG_OFFSET 0x60      /*  SD BD TX address register */
#define FSDMMC_BLK_CNT_REG_OFFSET 0x80             /*  Block reads and writes configuration registers */
#define FSDMMC_HDS_AXI_REG_CONF2_REG_OFFSET 0xa8   /*  AXI boundary configuration register 2 */
#define FSDMMC_NORMAL_INT_STATUS_REG_OFFSET 0xc0   /*  Interrupt status register */
#define FSDMMC_ERROR_INT_STATUS_REG_OFFSET 0xc4    /*  ERROR interrupt register */
#define FSDMMC_BD_ISR_REG_OFFSET 0xc8              /*  Data Transfer Interrupt Status Register */
#define FSDMMC_BD_STATUS_REG_OFFSET 0xcc           /*  BD descriptor register */
#define FSDMMC_STATUS_REG_OFFSET 0xd0              /*  Status register */
#define FSDMMC_BLOCK_REG_OFFSET 0xd4               /*  Block length register */
#define FSDMMC_CMD_RESP_1_REG_OFFSET 0xe0          /*  Command response register 1 */
#define FSDMMC_CMD_RESP_2_REG_OFFSET 0xe4          /*  Command response register 2 */
#define FSDMMC_CMD_RESP_3_REG_OFFSET 0xe8          /*  Command response register 3 */
#define FSDMMC_CMD_RESP_4_REG_OFFSET 0xec          /*  Command response register 4 */

/* 控制设置寄存器 */
#define FSDMMC_PERMDW_LIT_END       (0x0 << 10)
#define FSDMMC_PERMDW_BIG_END       (0x1 << 10)
#define FSDMMC_PERMDW_STD_END       (0x3 << 10)

#define FSDMMC_PERMDR_LIT_END       (0x0 << 8)
#define FSDMMC_PERMDR_BIG_END       (0x1 << 8)
#define FSDMMC_PERMDR_STD_END       (0x3 << 8)

/* 复位控制寄存器 */
#define FSDMMC_SOFTWARE_RESET_SRST  BIT(0)  /* 控制器软复位 */
#define FSDMMC_SOFTWARE_RESET_BDRST BIT(2) /* DMA BD 清 0 */
#define FSDMMC_SOFTWARE_RESET_CFCLF BIT(3) /* 卡插入拔出状态触发标志清 0 */

/* 卡检测寄存器 */
#define FSDMMC_SD_SEN_REG_CREFR BIT(1)                             /* 卡拔出时自动释放 AXI 总线选择 */
#define FSDMMC_SD_SEN_REG_CRES  BIT(2)                             /* CARD 在位状态标志选择 0： 卡在位-0，不在位-1 1: 卡在位-1，不在位-0 */
#define FSDMMC_SD_SEN_REG_DEBNCE(x) ((x << 8) & GENMASK(31, 8))    /* 去抖时钟分频参数 */

/* 中断使能寄存器 */
#define FSDMMC_NORMAL_INT_EN_ECC    BIT(0) /* 命令完成中断使能 */
#define FSDMMC_NORMAL_INT_EN_ECCRCE BIT(1) /* 卡拔出中断使能 */
#define FSDMMC_NORMAL_INT_EN_ECIE BIT(15) /* 错误中断使能 */

/* ERROR中断使能寄存器 */
#define FSDMMC_ERROR_INT_EN_CNR BIT(4)   /* Command response error interrupted */
#define FSDMMC_ERROR_INT_EN_CIR BIT(3)   /* 命令索引错误中断使能 */
#define FSDMMC_ERROR_INT_EN_CCRCE BIT(1) /* 命令 CRC 错误中断使能 */
#define FSDMMC_ERROR_INT_EN_CTE BIT(0)   /* 命令超时中断使能 */

/* 数据传输中断使能寄存器 */
#define FSDMMC_BD_ISR_EN_ETRS BIT(0)      /* DMA 传输完成中断使能 */
#define FSDMMC_BD_ISR_EN_EDTE BIT(3)      /* 数据超时中断使能 */
#define FSDMMC_BD_ISR_EN_ECMDE BIT(4)     /* 命令响应错误中断使能 */
#define FSDMMC_BD_ISR_EN_ETRE BIT(5)      /* 传输错误中断使能 */
#define FSDMMC_BD_ISR_EN_ENRCRCE BIT(6)   /* CRC 校验错误中断使能 */
#define FSDMMC_BD_ISR_EN_EDATFRAXE BIT(7) /* AXI 总线错误中断使能 */
#define FSDMMC_BD_ISR_EN_RESPE BIT(8)     /* 读 SD 卡操作，AXI BR 通道完成中断 */
#define FSDMMC_BD_ISR_EN_EDAISE BIT(15)   /* DMA 错误中断使能 */
#define FSDMMC_BD_ISR_ALL_MASK (FSDMMC_BD_ISR_EN_ETRS | FSDMMC_BD_ISR_EN_EDTE |         \
                                FSDMMC_BD_ISR_EN_ECMDE | FSDMMC_BD_ISR_EN_ETRE |        \
                                FSDMMC_BD_ISR_EN_ENRCRCE | FSDMMC_BD_ISR_EN_EDATFRAXE | \
                                FSDMMC_BD_ISR_EN_RESPE | FSDMMC_BD_ISR_EN_EDAISE)

/*  中断状态寄存器 */
#define FSDMMC_NORMAL_INT_STATUS_EI BIT(15) /* 命令错误中断 */
#define FSDMMC_NORMAL_INT_STATUS_CR BIT(1)  /* 卡移除中断 */
#define FSDMMC_NORMAL_INT_STATUS_CC BIT(0)  /* 命令完成中断 */
#define FSDMMC_NORMAL_INT_STATUS_ALL_MASK (FSDMMC_NORMAL_INT_STATUS_EI | FSDMMC_NORMAL_INT_STATUS_CR | FSDMMC_NORMAL_INT_STATUS_CC)

/*  ERROR中断寄存器 */
#define FSDMMC_ERROR_INT_STATUS_CNR BIT(4)   /* 命令响应错误中断 */
#define FSDMMC_ERROR_INT_STATUS_CIR BIT(3)   /* 命令索引错误中断 */
#define FSDMMC_ERROR_INT_STATUS_CCRCE BIT(1) /* 命令 CRC 错误中断 */
#define FSDMMC_ERROR_INT_STATUS_CTE BIT(0)   /* 命令超时错误中断 */
#define FSDMMC_ERROR_INT_STATUS_ALL_MASK (FSDMMC_ERROR_INT_STATUS_CNR | FSDMMC_ERROR_INT_STATUS_CIR | FSDMMC_ERROR_INT_STATUS_CCRCE | FSDMMC_ERROR_INT_STATUS_CTE)

/*  数据传输中断状态寄存器 */
#define FSDMMC_BD_ISR_REG_DAIS BIT(15)   /* DMA 错误中断*/
#define FSDMMC_BD_ISR_REG_RESPE BIT(8)   /* 读 SD 卡操作，AXI BR 通道完成中断*/
#define FSDMMC_BD_ISR_REG_DATFRAX BIT(7) /* axi 总线强制释放中断*/
#define FSDMMC_BD_ISR_REG_NRCRC BIT(6)   /* 无 CRC 响应中断*/
#define FSDMMC_BD_ISR_REG_TRE BIT(5)     /* CRC 响应错误中断*/
#define FSDMMC_BD_ISR_REG_CMDE BIT(4)    /* 命令响应错误中断*/
#define FSDMMC_BD_ISR_REG_DTE BIT(3)     /* 超时中断*/
#define FSDMMC_BD_ISR_REG_TRS BIT(0)     /* DMA 传输完成中断*/

/*  状态寄存器 */
#define FSDMMC_STATUS_REG_DATMAST(x) (GENMASK(30,27) & ((x) << 27)) /* data_master 状态机 */
#define FSDMMC_STATUS_REG_CDIF        BIT(26)                       /* 卡在位标志 */
#define FSDMMC_STATUS_REG_CDRF        BIT(25)                       /* 卡不在位标志 */
#define FSDMMC_STATUS_REG_CLSL        BIT(24)                       /* 命令闲信号 */
#define FSDMMC_STATUS_REG_DLSL(x)    (GENMASK(23, 20) & ((x) << 20))    /* 线信号 */
#define FSDMMC_STATUS_REG_CDSL        BIT(19)                       /* 卡检测管脚信号 */
#define FSDMMC_STATUS_REG_CST(x)     (GENMASK(15, 12) & ((x) << 12))   /* cmd_host state 状态机 */
#define FSDMMC_STATUS_REG_CSM(x)     (GENMASK(11, 7) & ((x) << 7))
#define FSDMMC_STATUS_REG_DAT_AVA     BIT(6)                        /* DAT_AVA 当前命令状态流程运转完  */
#define FSDMMC_STATUS_REG_CRC_VALID   BIT(5)
#define FSDMMC_STATUS_REG_CICMD       BIT(0)                        /* RO 0x0 CMD 总线状态 */

/* FSDMMC_STATUS mask */
#define FSDMMC_STATUS_CMD_BUSY		(0x0 << 0)	/* R  */
#define FSDMMC_STATUS_CMD_READY		(0x1 << 0)	/* R  */
#define FSDMMC_STATUS_IDIE		    BIT(12)	/* R  */

#define FSDMMC_CLK_DIV_MASK           GENMASK(31, 0) /* 时钟分频系数 */
#define FSDMMC_SD_DRV_MASK            GENMASK(31, 0) /* 卡驱动相位配置参数 */
#define FSDMMC_SD_SAMP_MASK           GENMASK(31, 0) /* 卡采样相位配置参数 */

/* CMD mask */
#define FSDMMC_CMD_SETTING_RTS(x)  (GENMASK(1, 0) & ((x) << 0)) /* 0: No response 01: Response byte length 136 10: Response byte length 48 11: Response byte length 48 */
#define FSDMMC_CMD_SETTING_CRCE    BIT(3)        /* 0: CRC check is not performed on CMD response 1: CRC check is performed on CMD response */
#define FSDMMC_CMD_SETTING_CICE    BIT(4)        /* 0：CMD 响应时，不执行索引检查 1：CMD 响应时，执行索引检查 */
#define FSDMMC_CMD_SETTING_CMDTP(x) (GENMASK(7, 6) & ((x) << 6)) /* 命令类型 */
#define FSDMMC_CMD_SETTING_CMDI(x) (GENMASK(13, 8) & ((x) << 8)) /* 命令索引 */
#define FSDMMC_CMD_SETTING_TRTY(x) (GENMASK(15, 14) & ((x) << 14))  /* 10： adtc 指令 ,其它： 读写操作 */

#define FSDMMC_CMD_RESP_MASK               GENMASK(1, 0)
#define FSDMMC_CMD_NO_RESP                 0x0 /* 00：不响应  */
#define FSDMMC_CMD_RESP_136_BIT            0x1 /* 01：响应字节长度 136 */
#define FSDMMC_CMD_RESP_48_BIT             0x2 /* 10: 响应字节长度 48 */
#define FSDMMC_CMD_RESP_48_BIT_BUSY_CHECK  0x3 /* 11: 响应字节长度 48, check busy after resp */

#define FSDMMC_CMD_ARG_MASK                GENMASK(31, 0)

#define FSDMMC_CLK_DIVIDER(clk)  ((FSDMMC_CLK_FREQ_HZ / (2 * (clk))) - 1)  
#define FSDMMC_DEFAULT_DRV       1
#define FSDMMC_DEFAULT_SAMP      5
#define FSDMMC_SDCARD_CLK_HZ     50000000  /* 50MHz */

#define FSDMMC_SEN_DEBNCE 10000000   /* 10 MHz */
#define FSDMMC_CMD_TIMEOUT 10000000  /* 1s */
#define FSDMMC_DATA_TIMEOUT 40000000 /* 4S */

/* FSDMMC Register Operations */
#define FSDMMC_BASEADDR(ctrl_p) ((ctrl_p)->config.base_addr)
#define FSDMMC_READ_REG(ctrl_p, reg_offset) FtIn32(FSDMMC_BASEADDR(ctrl_p) + (u32)(reg_offset))
#define FSDMMC_WRITE_REG(ctrl_p, reg_offset, reg_value) FtOut32(FSDMMC_BASEADDR(ctrl_p) + (u32)(reg_offset), (u32)(reg_value))
#define FSDMMC_SET_BIT(ctrl_p, reg_offset, bit)  FtSetBit32(FSDMMC_BASEADDR(ctrl_p) + (u32)(reg_offset), (u32)(bit))
#define FSDMMC_CLR_BIT(ctrl_p, reg_offset, bit)  FtClearBit32(FSDMMC_BASEADDR(ctrl_p) + (u32)(reg_offset), (u32)(bit))

#define FSDMMC_SET_SD_SEN(ctrl_p, val) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_SD_SEN_REG_OFFSET, (val))
#define FSDMMC_GET_SD_SEN(ctrl_p) FSDMMC_READ_REG((ctrl_p), FSDMMC_SD_SEN_REG_OFFSET)

#define FSDMMC_SET_NORMAL_INT(ctrl_p, val) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_NORMAL_INT_EN_REG_OFFSET, (val))
#define FSDMMC_SET_ERROR_INT(ctrl_p, val) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_ERROR_INT_EN_REG_OFFSET, (val))
#define FSDMMC_SET_BD_ISR(ctrl_p, val) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_BD_ISR_EN_REG_OFFSET, (val))

#define FSDMMC_GET_NORMAL_INT(ctrl_p) FSDMMC_READ_REG((ctrl_p), FSDMMC_NORMAL_INT_EN_REG_OFFSET)
#define FSDMMC_GET_ERROR_INT(ctrl_p) FSDMMC_READ_REG((ctrl_p), FSDMMC_ERROR_INT_EN_REG_OFFSET)
#define FSDMMC_GET_BD_ISR(ctrl_p) FSDMMC_READ_REG((ctrl_p), FSDMMC_BD_ISR_EN_REG_OFFSET)

#define FSDMMC_GET_NORMAL_INT_STATUS(ctrl_p) FSDMMC_READ_REG((ctrl_p), FSDMMC_NORMAL_INT_STATUS_REG_OFFSET)
#define FSDMMC_GET_ERROR_INT_STATUS(ctrl_p) FSDMMC_READ_REG((ctrl_p), FSDMMC_ERROR_INT_STATUS_REG_OFFSET)
#define FSDMMC_GET_BD_ISR_STATUS(ctrl_p) FSDMMC_READ_REG((ctrl_p), FSDMMC_BD_ISR_REG_OFFSET)

/* write 1 clear */
#define FSDMMC_CLR_NORMAL_INT_STATUS(ctrl_p) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_NORMAL_INT_STATUS_REG_OFFSET, (0x1))
#define FSDMMC_CLR_ERROR_INT_STATUS(ctrl_p) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_ERROR_INT_STATUS_REG_OFFSET, (0x1))
#define FSDMMC_CLR_BD_ISR_STATUS(ctrl_p) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_BD_ISR_REG_OFFSET, (0x1))

#define FSDMMC_SET_CMD_TIMEOUT(ctrl_p, val) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_TIMEOUT_CMD_REG_OFFSET, (val))
#define FSDMMC_SET_DATA_TIMEOUT(ctrl_p, val) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_TIMEOUT_DATA_REG_OFFSET, (val))

#define FSDMMC_SET_CTRL_SETTING(ctrl_p, val)  FSDMMC_WRITE_REG((ctrl_p), FSDMMC_CONTROLL_SETTING_REG_OFFSET, (val))

#define FSDMMC_SET_SOFTWARE_RESET(ctrl_p, val) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_SOFTWARE_RESET_REG_OFFSET, (val))
#define FSDMMC_GET_SOFTWARE_RESET(ctrl_p) FSDMMC_READ_REG((ctrl_p), FSDMMC_SOFTWARE_RESET_REG_OFFSET)
#define FSDMMC_SET_SWR(ctrl_p, bit) FSDMMC_SET_BIT((ctrl_p), FSDMMC_SOFTWARE_RESET_REG_OFFSET, (bit))
#define FSDMMC_CLR_SWR(ctrl_p, bit) FSDMMC_CLR_BIT((ctrl_p), FSDMMC_SOFTWARE_RESET_REG_OFFSET, (bit))

#define FSDMMC_GET_STATUS(ctrl_p) FSDMMC_READ_REG((ctrl_p), FSDMMC_STATUS_REG_OFFSET) 

#define FSDMMC_SET_CLK_DIV(ctrl_p, val) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_CLOCK_DIV_REG_OFFSET, (val))
#define FSDMMC_SET_SD_DRV(ctrl_p, val) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_SD_DRV_REG_OFFSET, (val))
#define FSDMMC_SET_SD_SAMP(ctrl_p, val) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_SD_SAMP_REG_OFFSET, (val))

#define FSDMMC_SET_CMD(ctrl_p, val)  FSDMMC_WRITE_REG((ctrl_p), FSDMMC_CMD_SETTING_REG_OFFSET, (val))
#define FSDMMC_GET_CMD(ctrl_p) FSDMMC_READ_REG((ctrl_p), FSDMMC_CMD_SETTING_REG_OFFSET)

#define FSDMMC_SET_CMD_ARG(ctrl_p, val) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_ARGUMENT_REG_OFFSET, (val))
#define FSDMMC_GET_CMD_ARG(ctrl_p) FSDMMC_READ_REG((ctrl_p), FSDMMC_ARGUMENT_REG_OFFSET)

#define FSDMMC_GET_RESP_1(ctrl_p) FSDMMC_READ_REG((ctrl_p), FSDMMC_CMD_RESP_1_REG_OFFSET)
#define FSDMMC_GET_RESP_2(ctrl_p) FSDMMC_READ_REG((ctrl_p), FSDMMC_CMD_RESP_2_REG_OFFSET)
#define FSDMMC_GET_RESP_3(ctrl_p) FSDMMC_READ_REG((ctrl_p), FSDMMC_CMD_RESP_3_REG_OFFSET)
#define FSDMMC_GET_RESP_4(ctrl_p) FSDMMC_READ_REG((ctrl_p), FSDMMC_CMD_RESP_4_REG_OFFSET)

#define FSDMMC_SET_BLK_CNT(ctrl_p, val)  FSDMMC_WRITE_REG((ctrl_p), FSDMMC_BLK_CNT_REG_OFFSET, (val))
#define FSDMMC_SET_RX_BD(ctrl_p, val)  FSDMMC_WRITE_REG((ctrl_p), FSDMMC_DAT_IN_M_RX_BD_REG_OFFSET, (val))

#define FSDMMC_SET_TX_BD(ctrl_p, val)  FSDMMC_WRITE_REG((ctrl_p), FSDMMC_DAT_IN_M_TX_BD_REG_OFFSET, (val))

#define FSDMMC_SET_HDS_AXI_CONF1(ctrl_p ,val) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_HDS_AXI_REG_CONF1_REG_OFFSET, (val))
#define FSDMMC_SET_HDS_AXI_CONF2(ctrl_p ,val) FSDMMC_WRITE_REG((ctrl_p), FSDMMC_HDS_AXI_REG_CONF2_REG_OFFSET, (val))


#ifdef __cplusplus
}
#endif

#endif